Show language: C# VB.NET Both
The custom data can be presented to the user easily through;
-Web Controls: Keyoti.SearchEngine.Web.ResultItem.CustomData or <%# Container.CustomData %> in the ResultItem template
-SearchAgent: Keyoti.SearchEngine.Search.ResultItem.DocumentRecord.CustomData for programmatic searches
For example, in the ResultItem template, to show the custom data as-is.
<ResultItemTemplate> ...other elements such as the title... <%# Container.CustomData %> ... </ResultItemTemplate>
Furthermore, to perform processing on the data before presenting it to the user, in a Web context with the SearchResult control, the ItemCreated event can be handled
For example, if CustomData holds a date string, it can be processed like this;
protected void Sr1_ItemCreated(object sender, Keyoti.SearchEngine.Web.SearchResultItemEventArgs e)
{
if (e.Item is Keyoti.SearchEngine.Web.ResultItem){
Label dateLabel = e.Item.FindControl("dateLabel") as Label;
if (dateLabel != null){
try {
DateTime docDate = DateTime.Parse((e.Data as Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData);
dateLabel.Text = docDate.ToLongDateString();
}
catch (FormatException){
//wasn't a date
}
}
}
}
Protected Sub Sr1_ItemCreated(ByVal sender As Object, ByVal e As Keyoti.SearchEngine.Web.SearchResultItemEventArgs) Handles SearchResult1.ItemCreated
If (TypeOf e.Item Is Keyoti.SearchEngine.Web.ResultItem) Then
Dim dateLabel As Label = CType(e.Item.FindControl("dateLabel"), Label)
If (Not (dateLabel) Is Nothing) Then
Try
Dim docDate As DateTime = DateTime.Parse(CType(e.Data, Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData)
dateLabel.Text = docDate.ToLongDateString
Catch ex As FormatException
'wasn't a date
End Try
End If
End If
End Sub
Which will look for a Label control with the ID "dateLabel" (which should be added to the ResultItem template) and set it's Text to a formatted date.
Custom data (and use of dates for example) leads to the question of custom sorting, since it may be desirable to sort the results according to the additional data held. This is relatively simple through the Central Event System.
In this example it is assumed that the CustomData is either a date string (yyyy/mm/dd) or an empty string (which means that documents with dates will be handled as well as documents without). Two buttons will be added to allow the user to sort by date ascending or descending, instead of the standard keyword relevance sorting.
1. Two buttons are added to the HeaderTemplate
<asp:Button ID="sortDownBT" runat="server" OnClick="sortDownBT_Click" Text="Sort By Date (Newest)" /> <asp:Button ID="sortUpBT" runat="server" OnClick="sortUpBT_Click" Text="Sort By Date (Oldest)" />
2. Variables are added to the code-behind for the sorting
bool sortByDate = false;
SortDirection sortDirection = SortDirection.Descending;
Dim sortByDate As Boolean = False
Dim sortDirection As SortDirection = SortDirection.Descending
3. The button Click handlers are added to the code-behind, which set the sort variables and also tell the SearchResult control ("Sr1") to regenerate it's search results after the post-back
protected void sortDownBT_Click(object sender, EventArgs e)
{
sortByDate = true;
sortDirection = SortDirection.Descending;
Sr1.InvalidateChildControlHierarchy();
}
protected void sortUpBT_Click(object sender, EventArgs e)
{
sortByDate = true;
sortDirection = SortDirection.Ascending ;
Sr1.InvalidateChildControlHierarchy();
}
Protected Sub sortDownBT_Click(ByVal sender As Object, ByVal e As System.EventArgs)
sortByDate = True
sortDirection = sortDirection.Descending
Sr1.InvalidateChildControlHierarchy()
End Sub
Protected Sub sortUpBT_Click(ByVal sender As Object, ByVal e As EventArgs)
sortByDate = True
sortDirection = sortDirection.Ascending
Sr1.InvalidateChildControlHierarchy()
End Sub
4. In the Page_Load handler, the Central Event System's "Action" event is hooked up, and filter load level set to include custom data.
protected void Page_Load(object sender, EventArgs e)
{
Sr1.FilterLoadLevel = Keyoti.SearchEngine.Search.FilterLoadLevel.Everything;
Sr1.Configuration.CentralEventDispatcher.Action += new Keyoti.SearchEngine.Events.ActionEventHandler(CentralEventDispatcher_Action);
}
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Sr1.FilterLoadLevel = Keyoti.SearchEngine.Search.FilterLoadLevel.Everything
AddHandler (Sr1.Configuration.CentralEventDispatcher.Action), AddressOf CentralEventDispatcher_Action
End Sub
5. And CentralEventDispatcher_Action is added, which will call for the sorting to be done at the appropriate time
void CentralEventDispatcher_Action(object sender, Keyoti.SearchEngine.Events.ActionEventArgs e)
{
if (sortByDate && e.ActionData.Name == Keyoti.SearchEngine.Events.ActionName.ResultItemsFinalized)
{
Keyoti.SearchEngine.Utils.ResultItemList resultItems = e.ActionData.Data as Keyoti.SearchEngine.Utils.ResultItemList;
resultItems.Sort(new DocumentDateComparer(sortDirection));
}
}
Private Sub CentralEventDispatcher_Action(ByVal sender As Object, ByVal e As Keyoti.SearchEngine.Events.ActionEventArgs)
If (sortByDate _
AndAlso (e.ActionData.Name = Keyoti.SearchEngine.Events.ActionName.ResultItemsFinalized)) Then
Dim resultItems As Keyoti.SearchEngine.Utils.ResultItemList = CType(e.ActionData.Data, Keyoti.SearchEngine.Utils.ResultItemList)
resultItems.Sort(New DocumentDateComparer(sortDirection))
End If
End Sub
The 'if' is satisfied when date sorting is enabled and the engine signals that the results are finalized. At this point the results are sorted by relevance, so the DocumentDateComparer is used to re-sort the results by date. The comparer class is fairly long because it handles documents with and without dates, as well as any formatting errors in the date strings.
class DocumentDateComparer : IComparer<Keyoti.SearchEngine.Search.ResultItem>
//NOTE: .NET1 users, the above line should be "class DocumentDateComparer : IComparer"
{
SortDirection sortDirection;
public DocumentDateComparer(SortDirection sortDirection)
{
this.sortDirection = sortDirection;
}
public int Compare(Keyoti.SearchEngine.Search.ResultItem x, Keyoti.SearchEngine.Search.ResultItem y)
//NOTE: .NET1 users, the above line should be "public int Compare(object x, object y)"
{
string xData = (x as Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData;
string yData = (y as Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData;
if(xData.Length==0 && yData.Length>0) return 1;
if(yData.Length==0 && xData.Length>0) return -1;
if(xData.Length==0 && yData.Length==0)return 0;
DateTime xDate, yDate;
try
{
xDate = DateTime.Parse(xData);
}
catch (FormatException)
{
//not a date, so make it historic so that it ends up lower in the sort order
xDate = DateTime.MinValue;
}
try
{
yDate = DateTime.Parse(yData);
}
catch (FormatException)
{
//not a date, so make it historic so that it ends up lower in the sort order
yDate = DateTime.MinValue;
}
if(sortDirection == SortDirection.Descending)
return yDate.CompareTo(xDate);
else
return xDate.CompareTo(yDate);
}
}
Class DocumentDateComparer
Implements IComparer(Of Keyoti.SearchEngine.Search.ResultItem)
'NOTE: .NET1 users, above line should be "Implements IComparer"
Private sortDirection As SortDirection
Public Sub New(ByVal sortDirection As SortDirection)
MyBase.New()
Me.sortDirection = sortDirection
End Sub
Public Function Compare(x As Keyoti.SearchEngine.Search.ResultItem, y As Keyoti.SearchEngine.Search.ResultItem) _
As Integer Implements IComparer(of Keyoti.SearchEngine.Search.ResultItem).Compare
'NOTE: .NET1 users, above line should be Public Function Compare(ByVal x As Object, ByVal y As Object) _
' As Integer Implements IComparer.Compare"
Dim xData As String = CType(x, Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData
Dim yData As String = CType(y, Keyoti.SearchEngine.Search.ResultItem).DocumentRecord.CustomData
If ((xData.Length = 0) _
AndAlso (yData.Length > 0)) Then
Return 1
End If
If ((yData.Length = 0) _
AndAlso (xData.Length > 0)) Then
Return -1
End If
If ((xData.Length = 0) _
AndAlso (yData.Length = 0)) Then
Return 0
End If
Dim yDate As DateTime
Dim xDate As DateTime
Try
xDate = DateTime.Parse(xData)
Catch ex As FormatException
'not a date, so make it historic so that it ends up lower in the sort order
xDate = DateTime.MinValue
End Try
Try
yDate = DateTime.Parse(yData)
Catch ex As FormatException
'not a date, so make it historic so that it ends up lower in the sort order
yDate = DateTime.MinValue
End Try
If (sortDirection = sortDirection.Descending) Then
Return yDate.CompareTo(xDate)
Else
Return xDate.CompareTo(yDate)
End If
End Function
End Class